package service

import (
	"a-common/constant"
	dom "a-common/domain"
	"a-common/myerr"
	"a-common/utils/excel"
	"a-common/utils/tree"
	"a-system/dao"
	"a-system/domain/entity"
	"errors"
	"fmt"
	"mime/multipart"
	"strconv"
	"strings"
	"sync"

	"a-common/utils/oss"

	"github.com/gofiber/fiber/v2"
	"github.com/xuri/excelize/v2"
)

var (
	userServiceTemp *UserService
	sysUserDao      = dao.NewSysUserDao()
	userServiceOnce sync.Once
)

type UserService struct{}

func NewSysUserService() *UserService {
	userServiceOnce.Do(func() {
		userServiceTemp = &UserService{}
	})
	return userServiceTemp
}

// List 分页
func (m *UserService) List(args *entity.UserDto) (dom.PageVo, error) {
	return sysUserDao.List(args, false)
}

// Export 导出
func (m *UserService) Export(args *entity.UserDto) (*excelize.File, error) {
	pageVo, err := sysUserDao.List(args, true)
	if err != nil {
		return nil, err
	}
	return excel.NormalDynamicExport(pageVo.Rows, "Sheet1", "用户表", "", true, false, map[string]string{})
}

// ImportTemplate 获取导入模板
// func (m *userService) ImportTemplate(c *fiber.Ctx) error {
// 	return c.SendFile("./uploads/template/user_temp.xlsx")
// }

// Import 导入
func (m *UserService) Import(file *multipart.FileHeader, updateSupport int, account string) (string, error) {
	// 打开数据流
	src, err := file.Open()
	if err != nil {
		return "", err
	}
	defer func(src multipart.File) {
		_ = src.Close()
	}(src)

	// 读取数据流
	f, err := excelize.OpenReader(src)
	if err != nil {
		return "", err
	}
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(updateSupport, err)
		}
	}()

	importList := []entity.SysUserImportVo{}
	err = excel.ImportExcel(f, &importList, 1, 2)
	if err != nil {
		return "", err
	}
	return sysUserDao.ImportData(updateSupport, importList, account)
}

// Get 查
func (m *UserService) Get(userId string, uid int64) (resp map[string]any, err error) {
	// 获取岗位列表
	posts, err := sysPostDao.ListAll()
	if err != nil {
		return
	}

	// 获取角色列表
	rolesAll, err := sysRoleDao.ListAll()
	if err != nil {
		return
	}
	var roles []entity.SysRoleVo
	if uid == constant.ADMIN_ID {
		roles = rolesAll
	} else {
		for _, r := range rolesAll {
			if r.RoleId != constant.ADMIN_ID {
				roles = append(roles, r)
			}
		}
	}

	if userId != "" {
		// 将字符串转换为int64
		uId, _err := strconv.ParseInt(userId, 10, 64)
		if _err != nil {
			return resp, _err
		}

		user, _err := sysUserDao.Get(uId)
		if _err != nil {
			return resp, _err
		}

		// 校验用户是否具有数据权限
		has, _err := sysUserDao.CheckUserDataScope(user.DeptId, 0, uid)
		if _err != nil {
			return resp, _err
		}
		if !has {
			return resp, myerr.ERR_SYS_403
		}

		// 获取拥有的岗位ID
		postIds, _err := sysUserDao.GetPostIdsByUserId(uId)
		if _err != nil {
			return resp, _err
		}

		// 获取拥有的角色ID
		roleIds, _err := sysUserDao.GetRoleIdsByUserId(uId)
		if _err != nil {
			return resp, _err
		}

		resp = make(map[string]any, 5)
		resp["data"] = user
		resp["roles"] = roles
		resp["posts"] = posts
		resp["postIds"] = postIds
		resp["roleIds"] = roleIds
		return
	} else {
		resp = make(map[string]any, 2)
		resp["roles"] = roles
		resp["posts"] = posts
		return
	}
}

// Del 删
func (m *UserService) Del(ids string) (int64, error) {
	return sysUserDao.Del(ids)
}

// Add 增
func (m *UserService) Add(args *entity.UserDto, uid int64) error {
	// 校验数据操作权限
	has, err := sysUserDao.CheckUserDataScope(0, args.DeptId, uid)
	if err != nil {
		return err
	}
	if !has {
		return myerr.ERR_SYS_403
	}
	// 校验账号是否重复
	has, err = sysUserDao.CheckUserNameUnique(args.UserName, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在账号")
	}
	// 校验昵称是否重复
	has, err = sysUserDao.CheckNickNameUnique(args.NickName, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在昵称")
	}
	// 校验号码是否重复
	has, err = sysUserDao.CheckPhoneUnique(args.Phonenumber, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在号码")
	}
	// 校验邮箱是否重复
	has, err = sysUserDao.CheckEmailUnique(args.Email, args.UserId)
	if err != nil {
		return err
	}
	if has {
		return errors.New("已存在邮箱")
	}
	return sysUserDao.Add(args)
}

// Edit 改
func (m *UserService) Edit(args *entity.UserDto, uid int64) error {
	// 不允许操作根用户
	if args.UserId == constant.ADMIN_ID && uid != constant.ADMIN_ID {
		return myerr.ERR_SYS_403
	}

	userVo, err := sysUserDao.Get(args.UserId)
	if err != nil {
		return err
	}
	// 校验用户是否有数据权限(校验是否可操作)
	has, err := sysUserDao.CheckUserDataScope(userVo.DeptId, args.DeptId, uid)
	if err != nil || !has {
		return myerr.ERR_SYS_403
	}
	return sysUserDao.Edit(args)
}

// ChangeStatus 切换状态
func (m *UserService) ChangeStatus(args *entity.UserDto, uid int64, account string) (int64, error) {
	// 校验用户是否有数据权限(校验是否可操作)
	userVo, err := sysUserDao.Get(args.UserId)
	if err != nil {
		return 0, err
	}
	has, err := sysUserDao.CheckUserDataScope(userVo.DeptId, args.DeptId, uid)
	if err != nil || !has {
		return 0, myerr.ERR_SYS_403
	}
	return sysUserDao.ChangeStatus(args.UserId, args.Status, account)
}

// ResetPwd 重置密码
func (m *UserService) ResetPwd(args *entity.UserDto, uid int64, account string) (int64, error) {
	// 校验用户是否有数据权限(校验是否可操作)
	userVo, err := sysUserDao.Get(args.UserId)
	if err != nil {
		return 0, err
	}
	has, err := sysUserDao.CheckUserDataScope(userVo.DeptId, args.DeptId, uid)
	if err != nil {
		return 0, err
	}
	if !has {
		return 0, myerr.ERR_SYS_403
	}
	return sysUserDao.UpdatePwd(args.UserId, args.Password, account)
}

// UpdatePwd 修改密码
func (m *UserService) UpdatePwd(args *entity.UserDto, uid int64, account string) (int64, error) {
	vUser, err := sysUserDao.Get(uid)
	if err != nil {
		return 0, err
	}
	// 校验旧密码
	if !cryptUtils.DeCrypt(vUser.Password, args.OldPassword) {
		return 0, errors.New("密码错误")
	}
	// 新旧密码不能一致
	if cryptUtils.DeCrypt(vUser.Password, args.NewPassword) {
		return 0, errors.New("新旧密码不能一致")
	}
	return sysUserDao.UpdatePwd(uid, args.NewPassword, account)
}

// Avatar 头像上传
func (m *UserService) Avatar(file *multipart.FileHeader, uid int64, account string) (string, error) {
	// 创建保存上传文件的路径
	filePath := "/profile/avatar/" + account + "." + strings.Split(file.Filename, ".")[1]

	// 上传文件
	err := oss.New().PutObject(filePath, file)
	if err != nil {
		return "", err
	}

	// 更新用户头像路径
	if err := sysUserDao.EditByAvatar(uid, filePath); err != nil {
		return "", err
	}

	// 拼接返回文件访问路径
	return filePath, nil
}

// GetAvatar 获取头像
func (m *UserService) GetAvatar(c *fiber.Ctx) error {
	// 获取下载文件的路径
	filename := c.Params("*")
	filepath := "./uploads/profile/avatar/" + filename

	// 读取文件内容
	// file, err := os.ReadFile(filepath)
	// if err != nil {
	// 	res.ServerFail(c, res.FILE_ERR_READ, err)
	// }

	// 设置响应头，告诉浏览器这是一个可下载的文件
	// c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))

	// return c.Send(file)
	return c.SendFile(filepath)
}

// DeptTree 获取部门树
func (m *UserService) DeptTree() (treeData []map[string]any, err error) {
	// 获取部门数据
	rows, err := dao.NewSysDeptDao().GetAll()
	if err != nil || len(rows) == 0 {
		return
	}
	// 构建部门树
	mp := make(map[string]string, 2)
	mp["id"] = "deptId"
	mp["label"] = "deptName"
	treeData = tree.GenerateTree(rows, &tree.TreeConfig{
		Rid:        0,
		IdName:     "deptId",
		PidName:    "parentId",
		WeightName: "orderNum",
		Mapper:     mp,
	})
	return
}

// AuthRole 根据用户编号获取授权角色
func (m *UserService) AuthRole(userId, uid int64) (fiber.Map, error) {
	userVo, err := sysUserDao.Get(userId)
	if err != nil {
		return nil, err
	}
	roleVos, err := sysRoleDao.ListAll()
	if err != nil {
		return nil, err
	}

	var rVos []entity.SysRoleVo
	if uid != constant.ADMIN_ID {
		for _, item := range roleVos {
			if item.RoleId != constant.ADMIN_ID {
				rVos = append(rVos, item)
			}
		}
	} else {
		rVos = roleVos
	}
	return fiber.Map{
		"user":  userVo,
		"roles": rVos,
	}, nil
}

// InsertAuthRole 用户授权角色
func (m *UserService) InsertAuthRole(args *entity.UserDto, uid int64) error {
	// 校验用户是否有数据权限(校验是否可操作)
	userVo, err := sysUserDao.Get(args.UserId)
	if err != nil {
		return err
	}
	has, err := sysUserDao.CheckUserDataScope(userVo.DeptId, 0, uid)
	if err != nil {
		return err
	}
	if !has {
		return myerr.ERR_SYS_403
	}
	// 更新用户角色
	return sysUserDao.InsertUserAuth(args.UserId, args.RoleIds)
}

// Profile 查询用户个人信息
func (m *UserService) Profile(uid int64) (fiber.Map, error) {
	user, err := sysUserDao.Get(uid)
	if err != nil {
		return nil, err
	}

	roleVos, err := sysRoleDao.GetRoleByUserId(uid)
	if err != nil {
		return nil, err
	}
	var roleGroup string
	for _, item := range roleVos {
		if roleGroup == "" {
			roleGroup = item.RoleName
		} else {
			roleGroup = roleGroup + "," + item.RoleName
		}
	}

	postVos, err := sysPostDao.GetPostByUserId(uid)
	if err != nil {
		return nil, err
	}
	var postGroup string
	for _, item := range postVos {
		if postGroup == "" {
			postGroup = item.PostName
		} else {
			postGroup = postGroup + "," + item.PostName
		}
	}

	return fiber.Map{
		"user":      user,
		"roleGroup": roleGroup,
		"postGroup": postGroup,
	}, nil
}

// GetSelectList 获取用户下拉列表
func (m *UserService) GetSelectList() ([]entity.SysUserSelectListVo, error) {
	return sysUserDao.GetSelectList()
}
